package com.denlaku.longan.util;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

/**
 * @author tianx
 */
public final class Maps {
    private static final int MIN_CAPACITY = 2;

    private static final float LOAD_FACTOR = 0.75f;

    /**
     * 创建空HashMap
     * @param <K> 键的类型
     * @param <V> 值的类型
     * @return 空HashMap
     */
    public static <K, V> Map<K, V> empty() {
        return ofSize(MIN_CAPACITY);
    }

    /**
     * 创建指定容量的HashMap
     * @param size 容量大小
     * @param <K> 键的类型
     * @param <V> 值的类型
     * @return HashMap
     */
    public static <K, V> Map<K, V> ofSize(int size) {
        return ofSize(size, LOAD_FACTOR);
    }

    /**
     * 创建指定容量、加载因子的HashMap
     * @param size 容量大小
     * @param loadFactor 加载因子
     * @param <K> 键的类型
     * @param <V> 值的类型
     * @return HashMap
     */
    public static <K, V> Map<K, V> ofSize(int size, float loadFactor) {
        int finalSize = Math.max(size, MIN_CAPACITY);
        float finalLoadFactor = loadFactor <= 0 || loadFactor > 1 ? LOAD_FACTOR : loadFactor;
        return new HashMap<>(finalSize, finalLoadFactor);
    }

    public static <K, V> Map<K, V> of(K key, V value) {
        Map<K, V> map = Maps.ofSize(2);
        map.put(key, value);
        return map;
    }

    public static <K, V> int size(Map<K, V> map) {
        return map == null ? 0 : map.size();
    }

    public static <K, V> Collection<V> values(Map<K, V> map) {
        return map != null ? map.values() : Lists.empty();
    }

    public static <K, V> V get(Map<K, V> map, K key) {
        return get(map, key, null);
    }

    public static <K, V> V get(Map<K, V> map, K key, V defaultValue) {
        return map != null ? map.get(key) : defaultValue;
    }

    public static <K, V> Boolean getBoolean(Map<K, V> map, K key) {
        V v = get(map, key);
        if (v != null) {
            if (v instanceof Boolean) {
                return (Boolean)v;
            }
            return Boolean.valueOf(v.toString());
        }
        return null;
    }

    private Maps() {
    }
}
